const vscode = require('vscode');
const path = require('path');
const fs = require('fs');
const util = require('../util');
const request = require('request');
const fetch = require('node-fetch');

function sendHttpRequest(opt) {
    return new Promise(function (resolve, reject) {
        setTimeout(() => {
            request(opt, function (error, response, body) {
                if (error) {
                    reject();
                } // Print the HTML for the Google homepage.
                resolve(body);
            });
        }, 100); //这里做下频控，防止hsfops面对那么多请求扛不住
    });
}

function getHsfVersionList(serviceName, env) {
    env = env || 'daily'; // 默认日常环境，线上环境为 online
    const host = util.getHsfHost(env == 'daily');
    let url = `http://${host}/hsfops/envs/${env}/services?filter=service&pattern=${serviceName}*`;
    return new Promise((resolve, reject) => {
        fetch(url).then(resp => resp.json()).then(resp => {
            console.log(resp);
            if(resp && resp.length) {
                const result = resp.map(item => {
                    const temp = item.dataId.split(':');
                    item.serviceNameAndVersion = item.dataId;
                    item.serviceName = temp[0];
                    item.version = temp[1];
                    delete item.dataId;
                    return item;
                });
                resolve(result);
            } else {
                reject(`${env}环境中未找到名为 ${serviceName} 的service！`);
            }
        }).catch(e => {
            console.error(e);
            reject(e);
        });
    });
}

function getArtifactId(serviceNameAndVersion, env) {
    env = env || 'daily'; // 默认日常环境，线上环境为 online
    const host = util.getHsfHost(env == 'daily');
    let getMetaDataUrl = `http://${host}/hsfops/envs/${env}/services/${serviceNameAndVersion}/metadata`;
    return new Promise((resolve, reject) => {
        fetch(getMetaDataUrl).then(resp => resp.json()).then(resp => {
            console.log(resp);
            if(resp && resp.codeSource) {
                // codeSource 到 artifactId 转换规则不确定
                // customer-platform-client-1.0.26.jar => customer-platform-client
                let matchResults = /([a-zA-z\.]+\.[a-z]+\b)?[-]?([a-zA-Z-]+[a-z]\b)?[-]?([0-9\.]+(-SNAPSHOT)?)\.jar/ig.exec(resp.codeSource);
                if (matchResults.length >= 3) {
                    const artifactId = matchResults[2];
                    resolve(artifactId);
                }
            } else {
                reject(`调用接口失败：${getMetaDataUrl}`);
            }
        }).catch(e => {
            console.error(e);
            reject(e);
        });
    });
}

function getDependencyInfo(artifactId) {
    let url = `http://repo.${util.getAbbHost()}/nexus/service/local/lucene/search?q=${artifactId}&collapseresults=true`;
    const config = {
        method: 'GET',
        headers: {'accept': 'application/json'}
    };
    return new Promise((resolve, reject) => {
        fetch(url, config).then(resp => resp.json()).then(resp => {
            if(resp && resp.data && resp.data.length) {
                const dependencyInfo = {
                    groupId: resp.data[0].groupId,
                    artifactId: resp.data[0].artifactId,
                    version: resp.data[0].version
                }
                resolve(dependencyInfo);
            } else {
                reject('');
            }
        }).catch(e => {
            console.error(e);
            reject(e);
        });
    });
}

function requestHsfopsForDetial(service, cb) {
    let serviceSplitArr = service.split(":");
    let serviceName = service;
    let env = "online";

    if (serviceSplitArr.length >= 2) { //对已经配置了版本号以及环境，就按照线下环境处理
        let versionPaserArray = /([0-9.]+)\.([a-zA-Z]+)/ig.exec(serviceSplitArr[1]);
        if (versionPaserArray) {
            env = "daily";
        }

    } else if (serviceSplitArr.length == 1) { //对没有配置版本号和环境的，那么就走正式环境
        //如果不明确指定版本，默认都是走正式的
        let queryServiceUrl = `http://${util.getHsfHost(false)}/hsfops/envs/online/services?filter=service&pattern=${serviceName}*`
        sendHttpRequest({
            url: queryServiceUrl,
            json: true,
            headers: {
                "content-type": "application/json"
            }
        }).then(queryResult => {
            if (queryResult && queryResult.length > 0) {
                // 取最大版本号
                let maxVersionServiceInfo = queryResult.reduce(function (itemA, itemB) {
                    // itemA
                    // . 0 itemB
                    // . 0.my 这里会不小心出现如上的情况，正常情况应该获取1.0.0而不是包含my的情况，所以下面做了个包含的判定，来决定是不是再进行比较。
                    return (itemA.dataId < itemB.dataId
                        ? (itemB.dataId.indexOf(itemA.dataId) == -1
                            ? itemB
                            : itemA)
                        : (itemA.dataId.indexOf(itemB.dataId) == -1
                            ? itemA
                            : itemB));
                })
                serviceName = maxVersionServiceInfo.dataId;
                console.log(serviceName);
                const host = util.getHsfHost(env == 'daily');
                let serviceInfoUrl = `http://${host}/hsfops/envs/${env}/services?filter=service&pattern=${serviceName}`;
                let metaDataUrl = `http://${host}/hsfops/envs/${env}/services/${serviceName}/metadata`;
                console.log(`serviceInfoUrl:${serviceInfoUrl}`);
                console.log(`metaDataUrl:${metaDataUrl}`);
                sendHttpRequest({
                    url: serviceInfoUrl,
                    json: true,
                    headers: {
                        "content-type": "application/json"
                    }
                }).then(serviceNormalInfo => {
                    sendHttpRequest({
                        url: metaDataUrl,
                        json: true,
                        headers: {
                            "content-type": "application/json"
                        }
                    }).then(serviceMetaInfo => {
                        if (serviceNormalInfo && serviceMetaInfo && serviceNormalInfo.length && serviceNormalInfo.length > 0 && serviceMetaInfo.codeSource) {
                            // jar:file:/home/admin/onetouch-file-bank/target/onetouch-file-bank/BOOT-INF/li
                            // cupoo.service.api-1.1.33.jar
                            // jar:file:/home/admin/onetouch-tax-orderfile/target/onetouch-tax-orderfile/BOO
                            // T -INF/lib/tax-orderfile-api-1.0.26.jar!/ /file-bank-api-1.0.9.jar!/
                            // codeSource真心是神坑啊，wtf，这块要做个处理,jar文件都是按照groupId-article-version.jar这个格式来做的，所以解析
                            // 也 只能这么解析.
                            let matchResults = /([a-zA-z\.]+\.[a-z]+\b)?[-]?([a-zA-Z-]+[a-z]\b)?[-]?([0-9\.]+(-SNAPSHOT)?)\.jar/ig.exec(serviceMetaInfo.codeSource);
                            let codeSource = null;
                            let groupId = null;
                            let artifactId = null;
                            let version = null;
                            if (matchResults.length >= 3) {
                                groupId = matchResults[1];
                                artifactId = matchResults[2];
                                version = matchResults[3];
                                let jarArgs = [
                                    artifactId
                                        ? artifactId
                                        : groupId
                                            ? groupId
                                            : null,
                                    version
                                ];
                                codeSource = jarArgs.join("-") + '.jar';
                            }
                            console.log(`source:${serviceMetaInfo.codeSource} output:${codeSource}`);
                            if (codeSource) {
                                let serviceInfo = {
                                    serviceName: serviceNormalInfo[0].dataId,
                                    serviceAppName: serviceNormalInfo[0].appName,
                                    serviceClassName: serviceMetaInfo.canonicalName,
                                    serviceJarFullName: codeSource,
                                    serviceArtifactId: (artifactId ? artifactId : (groupId ? groupId : null)),
                                    serviceArtifactVersion: version
                                }
                                
                                let mavenJarInfoSearchUrl = `http://mvnrepo.${util.getAbbHost()}/nexus/service/local/lucene/search?_dc=&a=${artifactId}&v=${version}&collapseresults=true`;
                                sendHttpRequest({
                                    url: mavenJarInfoSearchUrl,
                                    json: true,
                                    headers: {
                                        "content-type": "application/json"
                                    }
                                }).then(mavenInfo => {
                                    console.log(`mavenJarInfoSearchUrl:${mavenJarInfoSearchUrl}`);
                                    //要查取完整的坐标
                                    if (mavenInfo && mavenInfo.totalCount && mavenInfo.totalCount > 0) {
                                        serviceInfo.artifactInfo = {
                                            groupId: mavenInfo.data[0].groupId,
                                            artifactId: mavenInfo.data[0].artifactId,
                                            version: mavenInfo.data[0].version
                                        }
                                        cb(serviceInfo);
                                        console.log(serviceInfo);
                                    } else {
                                        throw new Error(`拉取maven的jar坐标有误 jar名称:${serviceInfo.serviceJarFullName} mavenJarInfoSearchUrl:${mavenJarInfoSearchUrl}`);
                                    }
                                });
                                

                            } else {
                                throw new Error(`Hsfops的Jar包格式有误 原始jar名称:${serviceMetaInfo.codeSource} 处理后名称:${codeSource} `);
                            }
                        } else {
                            throw new Error(`Hsfops信息拉取失败! serviceName${serviceName} 服务基本信息:${JSON.stringify(serviceNormalInfo)} 服务元信息:${JSON.stringify(serviceMetaInfo)}`);
                        }
                    })
                })
        
            }  
        });
        
    } else {
        throw new Error(`服务名格式不正确!应该为（类名：版本号.环境）格式 serviceName:${serviceName}`);
    }

   
}

module.exports = function(context) {
    // 注册命令，可以给命令配置快捷键或者右键菜单
    context.subscriptions.push(vscode.commands.registerCommand('extension.hsf.addService', function () {
        vscode.window.showInputBox({placeHolder: '请输入要添加的HSF完整服务名'}).then(serviceName => {
            console.log(serviceName);

            const env = 'online';
            getHsfVersionList(serviceName, env)
            .then(serviceList => {
                console.log(serviceList);
                return getArtifactId(serviceList[0].serviceNameAndVersion, env);
            }).then(artifactId => {
                console.log(artifactId);
                return getDependencyInfo(artifactId);
            }).then(dependencyInfo => {
                console.log(dependencyInfo);
            }).catch(e => {
                console.log(e);
            });
            return;

            var temp = serviceName.split('.');
            var key = temp[temp.length-1];
            let filePath = vscode.window.activeTextEditor.document.fileName;
            var content = require(filePath); // 这里的require要改成动态加载，因为有缓存
            if (!content.appname || !content.api || !content.dependency) {
                vscode.window.showInformationMessage('请在proxy配置文件中执行本命令！');
                return;
            }
            if(content.api[key]) {
                vscode.window.showInformationMessage('此service已存在，无需重复添加！');
                return;
            }
            try {
                requestHsfopsForDetial(serviceName, function(serviceInfo) {
                    content.api[key] = {interfaceName: serviceName};
                    const dependencyMap = {};
                    content.dependency.forEach(item => {
                        dependencyMap[item.groupId + '_' + item.artifactId] = true;
                    })
                    const artifactInfo = serviceInfo.artifactInfo;
                    // 防止重复添加依赖
                    if (!dependencyMap[artifactInfo.groupId + '_' + artifactInfo.artifactId]) {
                        content.dependency.push(serviceInfo.artifactInfo);
                    }
                    let text = `module.exports = ${util.formatToSimpleJSON(content, '  ', true)};\n`
                    vscode.window.activeTextEditor.edit(editBuilder => {
                        // 从开始到结束，全量替换
                        const end = new vscode.Position(vscode.window.activeTextEditor.document.lineCount + 1, 0);
                        editBuilder.replace(new vscode.Range(new vscode.Position(0, 0), end), text);
                    });
                    // 直接写入文件会默认就保存到磁盘了，不利于撤销
                    // fs.writeFileSync(filePath, text, 'utf-8');
                });
            } catch (e) {
                console.log(e);
                vscode.window.showErrorMessage('出现异常：' + e);
            }
        })
    }));
};